#include "PageSelectionShell.h"
#include "../../Utility/XXlogger.h"

XX_KEY_C(PageSelectionShell,kSigNeedUpdate,"sigNeedUpdate")

PageSelectionShell::PageSelectionShell(QObject *parent) : QObject(parent)
{
    _button_first = nullptr;
    _button_previous = nullptr;
    _label_page = nullptr;
    _button_next = nullptr;
    _button_last = nullptr;
    _lineEdit_pageSwitch = nullptr;
    _comBobox_availableCountPerPage = nullptr;
    _label_itemTotal = nullptr;

    _pageIndex = -1;
    _count = 0;
    _countPerPage = 10;
    _availableCountPerPage = {10,20,30,40,50};
    _pageCount = 0;
}

void PageSelectionShell::shell(QAbstractButton *first, QAbstractButton *previous, QLabel *page, QAbstractButton *next, QAbstractButton *last, QLineEdit *pageSwitch, QComboBox *availableCountPerPage, QLabel *total){
    _button_first = first;
    _button_previous = previous;
    _label_page = page;
    _button_next = next;
    _button_last = last;

    _lineEdit_pageSwitch = pageSwitch;
    _comBobox_availableCountPerPage = availableCountPerPage;
    _label_itemTotal = total;

    if(first) connect(first,&QAbstractButton::clicked,this,&PageSelectionShell::button_firstPage_onClicked);
    if(previous) connect(previous,&QAbstractButton::clicked,this,&PageSelectionShell::button_previousPage_onClicked);
    if(next) connect(next,&QAbstractButton::clicked,this,&PageSelectionShell::button_nextPage_onClicked);
    if(last) connect(last,&QAbstractButton::clicked,this,&PageSelectionShell::button_lastPage_onClicked);

    if(pageSwitch){
        connect(pageSwitch,&QLineEdit::textEdited,this,&PageSelectionShell::lineEdit_pageSwitch_onTextEdited);
        connect(pageSwitch,&QLineEdit::editingFinished,this,&PageSelectionShell::lineEdit_pageSwitch_onEditingFinished);
    }
    if(availableCountPerPage){
        connect(availableCountPerPage,SIGNAL(currentIndexChanged(const QString &)),this,SLOT(comboBox_availableCountPerPage_onCurrentIndexChanged(const QString &)));
    }
}

void PageSelectionShell::consetCountPerPage(int count, QList<int> available){
    reset(_count,count,available);
}

void PageSelectionShell::reset(int count, int pageIndex){
    reset(count,_countPerPage,_availableCountPerPage,pageIndex);
}
void PageSelectionShell::reset(int count, int countPerPage, QList<int> availableCountPerPage, int pageIndex){
    _countPerPage = countPerPage;

    bool needUpdate = false;
    bool needUpdateTemp = false;
    if(_availableCountPerPage != availableCountPerPage){
        setAvailableCountPerPageLess(countPerPage,availableCountPerPage,needUpdateTemp);
        if(needUpdateTemp)needUpdate=true;
    }
    setCountLess(count,needUpdateTemp); if(needUpdateTemp)needUpdate=true;
    setPageIndexLess(pageIndex,needUpdateTemp); if(needUpdateTemp)needUpdate=true;
    if(needUpdate){
        emit sigEvent(kSigNeedUpdate,QVariant());
    }
}
void PageSelectionShell::insertItem(int index){
    bool needUpdate = false;
    int startOfPage =_pageIndex*_countPerPage;
    int endOfPage =startOfPage+_countPerPage;
    if(index<endOfPage){
        needUpdate = true;
    }

    setCountLess(_count+1,needUpdate);
    if(needUpdate){
        emit sigEvent(kSigNeedUpdate,QVariant());
    }
}
void PageSelectionShell::appendItem(){
    setCount1(_count+1);
}
void PageSelectionShell::removeItemAtIndex(int index){
    bool needUpdate = false;
    int startOfPage =_pageIndex*_countPerPage;
    int endOfPage =startOfPage+_countPerPage;
    if(index<endOfPage){
        needUpdate = true;
    }

    setCountLess(_count-1,needUpdate);
    if(needUpdate){
        emit sigEvent(kSigNeedUpdate,QVariant());
    }
}
void PageSelectionShell::removeItemLast(){
    setCount1(_count-1);
}
bool PageSelectionShell::isCurrentPage(int index){
    int startOfPage =_pageIndex*_countPerPage;
    int endOfPage =startOfPage+_countPerPage;
    return index>=startOfPage && index<endOfPage;
}

void PageSelectionShell::nextPage(){
    setPageIndex1(_pageIndex+1);
}
void PageSelectionShell::previousPage(){
    setPageIndex1(_pageIndex-1);
}
int PageSelectionShell::getCurrentPageIndex(){
    return _pageIndex;
}
int PageSelectionShell::getPageCount(){
    return _pageCount;
}
int PageSelectionShell::getCountPerPage(){
    return _countPerPage;
}
int PageSelectionShell::getIndexFromRowInPage(int row){
    if(_pageIndex<=0){
        return row;
    }
    else{
        return _pageIndex * _countPerPage + row;
    }
}
int PageSelectionShell::getRowFromIndex(int index){
    return index%_countPerPage;
}
int PageSelectionShell::getBeginIndexInPage(){
    return _pageIndex * _countPerPage;
}
int PageSelectionShell::getCountInPage(){
    int index = _pageIndex * _countPerPage + _countPerPage;
    return index>_count ? _count%_countPerPage : _countPerPage;
}
bool PageSelectionShell::isIndexAtCurrentPage(int index){
    int begin = getBeginIndexInPage();
    int count = getCountInPage();
    return index>=begin&&count>index-begin;
}

QAbstractButton *PageSelectionShell::first(){
    return _button_first;
}
QAbstractButton *PageSelectionShell::previous(){
    return _button_previous;
}
QLabel *PageSelectionShell::page(){
    return _label_page;
}
QAbstractButton *PageSelectionShell::next(){
    return _button_next;
}
QAbstractButton *PageSelectionShell::last(){
    return _button_last;
}

QLineEdit *PageSelectionShell::pageSwitch(){
    return _lineEdit_pageSwitch;
}
QComboBox* PageSelectionShell::availableCountPerPage(){
    return _comBobox_availableCountPerPage;
}
QLabel* PageSelectionShell::itemTotal(){
    return _label_itemTotal;
}

void PageSelectionShell::setCountPerPageLess(int count, bool &needUpdate){
    if(_countPerPage==count){
        return;
    }
    _countPerPage = count;
    _pageCount = _count/_countPerPage;
    if(_count%_countPerPage){
        ++_pageCount;
    }
    setPageIndexLess(0,needUpdate);
    needUpdate = true;

    updateButtonState();
    updatePageTitle();
    updatePageSwitch();
    updateCountTitle();
}
void PageSelectionShell::setCountLess(int count, bool &needUpdate){
    if(count == _count){
        return ;
    }
    int lastPageCount = _pageCount;
    int lastCount = _count;
    _count = count;
    _pageCount = _count/_countPerPage;
    if(_count%_countPerPage){
        ++_pageCount;
    }

    // 如果当前页总数是减少
    if(_pageCount<lastPageCount){
        // 当前页编号是修改前的最后一页
        if(_pageIndex+1>=lastPageCount){
            if(_pageCount>0){
                setPageIndexLess(_pageCount-1,needUpdate);
            }
            else {
                setPageIndexLess(0,needUpdate);
            }
        }
    }

    // 当前页编号是最后一页
    if(_pageIndex+1>=_pageCount){
        needUpdate = true;
    }

    // 如果当前页总数在增加
    if(_pageCount>lastPageCount && 0==lastPageCount){
        needUpdate = true;
    }

    if(lastCount==-1){
        needUpdate = true;
    }

    updateButtonState();
    updatePageTitle();
    updatePageSwitch();
    updateCountTitle();
}
void PageSelectionShell::setCount1(int count){
    bool needUpdate = false;
    setCountLess(count,needUpdate);
    if(needUpdate){
        emit sigEvent(kSigNeedUpdate,QVariant());
    }
}
void PageSelectionShell::setPageIndexLess(int index, bool &needUpdate){
    if(index>_pageCount){
        return;
    }
    int temp = _pageIndex;
    _pageIndex = index;
    updateButtonState();
    updatePageTitle();

    if(temp != index){
        needUpdate = true;
    }
}
void PageSelectionShell::setPageIndex1(int index){
    if(index>_pageCount || index<0 || (_pageCount>0&&index==_pageCount)){
        return;
    }
    int temp = _pageIndex;
    _pageIndex = index;
    updateButtonState();
    updatePageTitle();

    if(temp != index){
        emit sigEvent(kSigNeedUpdate,QVariant());
    }
}
void PageSelectionShell::setAvailableCountPerPageLess(int count, QList<int> available, bool &needUpdate){
    if(!availableCountPerPage()){
        return;
    }
    QString temp = availableCountPerPage()->currentText();
    disconnect(availableCountPerPage(),SIGNAL(currentIndexChanged(const QString &)),this,SLOT(comboBox_availableCountPerPage_onCurrentIndexChanged(const QString &)));
    availableCountPerPage()->clear();
    foreach(int a, available){
        availableCountPerPage()->addItem(QString::number(a));
    }
    availableCountPerPage()->setCurrentText(QString::number(count));
    connect(availableCountPerPage(),SIGNAL(currentIndexChanged(const QString &)),this,SLOT(comboBox_availableCountPerPage_onCurrentIndexChanged(const QString &)));
    QString curr = availableCountPerPage()->currentText();
    needUpdate = temp!=curr;
}

void PageSelectionShell::updateCountTitle(){
    itemTotal()->setText(QString::number(_count));
}
void PageSelectionShell::updatePageTitle(){
    page()->setText(QString("%1/%2").arg(_pageIndex<0?1:_pageIndex+1).arg(0==_pageCount?1:_pageCount));
}
void PageSelectionShell::updateButtonState(){
    if(first()) first()->setEnabled(_pageIndex>0);
    if(previous()) previous()->setEnabled(_pageIndex>0);
    if(next()) next()->setEnabled(_pageIndex>=0&&_pageIndex+1<_pageCount);
    if(last()) last()->setEnabled(_pageIndex>=0&&_pageIndex+1<_pageCount);
}
void PageSelectionShell::updatePageSwitch(){
    QLineEdit *lineEdit = pageSwitch();
    if(!lineEdit){
        return;
    }
    lineEdit->setValidator(new QIntValidator(1,_pageCount));
    lineEdit->setText("");
}

void PageSelectionShell::button_firstPage_onClicked(){
    if(_pageIndex<0|| _pageCount<=1){
        xxLog("[BUG] invalid param. count:%d countPerPage:%d pageCount:%d pageIndex:%d",_count,_countPerPage,_pageCount,_pageIndex);
        return;
    }
    setPageIndex1(0);
}
void PageSelectionShell::button_previousPage_onClicked(){
    if(_pageIndex<0|| _pageCount<=1){
        xxLog("[BUG] invalid param. count:%d countPerPage:%d pageCount:%d pageIndex:%d",_count,_countPerPage,_pageCount,_pageIndex);
        return;
    }
    setPageIndex1(_pageIndex-1);
}
void PageSelectionShell::button_nextPage_onClicked(){
    if(_pageIndex>=_pageCount|| _pageCount<=1){
        xxLog("[BUG] invalid param. count:%d countPerPage:%d pageCount:%d pageIndex:%d",_count,_countPerPage,_pageCount,_pageIndex);
        return;
    }
    setPageIndex1(_pageIndex+1);
}
void PageSelectionShell::button_lastPage_onClicked(){
    if(_pageIndex>=_pageCount || _pageCount<=1){
        xxLog("[BUG] invalid param. count:%d countPerPage:%d pageCount:%d pageIndex:%d",_count,_countPerPage,_pageCount,_pageIndex);
        return;
    }
    setPageIndex1(_pageCount-1);
}
void PageSelectionShell::lineEdit_pageSwitch_onTextEdited(const QString &text){
    QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender());
    QString t = text;
    int p = 0;
    if(nullptr!=lineEdit->validator() && QValidator::Acceptable != lineEdit->validator()->validate(t,p)){
        QString s;
        lineEdit->validator()->fixup(s);
        lineEdit->setText(s);
    }
}
void PageSelectionShell::lineEdit_pageSwitch_onEditingFinished(){
    QLineEdit *lineEdit = qobject_cast<QLineEdit*>(sender());
    setPageIndex1(lineEdit->text().toInt()-1);
    lineEdit->setText("");
}
void PageSelectionShell::comboBox_availableCountPerPage_onCurrentIndexChanged(const QString &text){
    if(text.isEmpty()){
        return;
    }
    bool needUpdate = false;
    setCountPerPageLess(text.toInt(),needUpdate);
    if(needUpdate){
        emit sigEvent(kSigNeedUpdate,QVariant());
    }
}
